<!doctype html><meta http-equiv=content-type content=text/html ; charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>高性能Go并发建议</title><meta name=referrer content=no-referrer><body data-category=default data-clipid=1566379143><div class="mx-wc-main  yue"><div><div><div><div><p>1.管道chan吞吐极限10,000,000，单次Put,Get耗时大约100ns/op，无论是采用单Go程，还是多Go程并发(并发数:100, 10000, 100000)，耗时均没有变化，Go内核这对chan进行优化。<p><b>解决之道</b>
：在系统设计时，避免使用管道chan传递主业务数据，避免将业务流程处理流程分割到对个Go程中执行，这样做减少chan传输耗时，和Go程调度耗时，性能会有很大的提升。<p><b>案例分析</b>
：nsq和nats都是实时消息队列，nsq在客户端端和服务端大量使用chan转发消息，导致性能不佳，只有100,000／s；而nats服务端在分发消息流程中，没有使用chan，只在客户端接收时使用chan，性能可达到1,000,000／s。<p>2.互斥锁Mutex在单Go程时Lock,Unlock耗时大约20ns/op，但是采用多Go程时，性能急剧下降，并发越大耗时越长，在Go1.5并发数达到1024耗时900ns/op，Go1.6优化到300ns/op，究其原因，是构建在CPU的原子操作之上，抢占过于频繁将导致，消耗大量CPU时钟，进而CPU多核无法并行。<p><b>解决之道</b>
：采用分区，将需要互斥保护的数据，分成多个固定分区(建议是2的整数倍，如256)，访问时先定位分区(不互斥)，这样就可降低多个Go程竞争1个数据分区的概率。<p><b>案例分析</b>
：Golang的Go程调度模块，在管理大量的Go程，使用的就是数据分区。<p>3.select异步操作在单管道时耗时120ns/op，但是随着管道数增加，性能线性下降，每增加1个管道增加100ns/op，究其原因，slelect时当chan数超过1后，Go内部是创建一个Go程，有它每1ms轮训的方式检查每个chan是否可用，而不是采用事件触发。<p><b>解决之道</b>
：在select中避免使用过多的管道chan分支，或者把无法用到的chan置为nil；解决select超时，避免使用单独的超时管道，应与数据返回管道共享。<p><b>案例分析</b>
：nsq和nats都是实时消息队列，由于nsq大量使用chan，这就必然导致大量使用select对多chan操作，结果是性能不高。<p>4.Go调度性能低下，当出现1,000,000Go程时，Go的调度器的性能急剧下降。<p><b>解决之道</b>
：避免动态创建Go程，服务端收到数据并处理的流程中，避免使用chan传递业务数据，这样会引起Go程调度。<p><b>案例分析</b>
：nsq和nats都是实时消息队列，由于nsq大量使用chan，这就必然导致在服务过程中，引起Go调度，结果是性能不高。<p>5.defer性能不高，每次defer耗时100ns，，在一个func内连续出现多次，性能消耗是100ns*n，累计出来浪费的cpu资源很大的。<p><b>解决之道</b>
：除了需要异常捕获时，必须使用defer；其它资源回收类defer，可以判断失败后，使用goto跳转到资源回收的代码区。<p><b>补充</b>
：defer 在 go1.8 快了一倍了。 <a href="https://links.jianshu.com/go?to=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%253A%2F%2Fgithub.com%2Fgolang%2Fgo%2Fissues%2F14939" target=_blank rel=nofollow,noindex>runtime: defer is slow · Issue #14939 · golang/go · GitHub</a><p>6.内存管理器性能低下，申请16字节的内存，单次消耗30ns，64字节单次消耗70ns，随着申请内存尺寸的增长，耗时会迅速增长。加上GC的性能在1.4, 1.5是都不高，直到1.6, 1.7才得到改善。<p><b>解决之道</b>
：建议使用pool，单次Put，Get的耗时大约在28ns，在并发情况下可达到18ns，比起每次创建，会节省很多的CPU时钟。<p><b>补充</b>
： 单纯看 Put, Get 耗时不高，但是 pool 取出来的是 interface{}，需要类型断言成实际类型，放进去的时候，还要把实际类型转换成 interface{}（虽然是自动的），这个转换的过程对于简单类型每次需要 30ns，复杂的结构体时间会长的多，所以这个开销算上的话，用 pool 方案反而会导致性能下降。<p>建议：<p>（1）尽可能的使用:=去初始化声明一个变量（在函数内部）；<p>（2）尽可能的使用字符代替字符串；<p>（3）尽可能的使用切片代替数组；<p>（4）尽可能的使用数组和切片代替映射（详见参考文献15）；<p>（5）如果只想获取切片中某项值，不需要值的索引，尽可能的使用for range去遍历切片，这比必须查询切片中的每个元素要快一些；<p>（6）当数组元素是稀疏的（例如有很多0值或者空值nil），使用映射会降低内存消耗；<p>（7）初始化映射时指定其容量；<p>（8）当定义一个方法时，使用指针类型作为方法的接受者；<p>（9）在代码中使用常量或者标志提取常量的值；<p>（10）尽可能在需要分配大量内存时使用缓存；<p>（11）使用缓存模板（参考 <a href="https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FUnknwon%2Fthe-way-to-go_ZH_CN%2Fblob%2Fmaster%2FeBook%2F15.7.md" target=_blank rel=nofollow,noindex>章节15.7</a>
）。</div></div></div></div><hr></div><div class=clipping-information><label>原网址: <a href=https://www.tuicool.com/articles/ruaM32J target=_blank referrerpolicy=no-referrer rel="noopener noreferrer">访问</a></label><br><label>创建于: 2019-08-21 17:19:03</label><br><label>目录: default</label><br><label>标签: <code>go</code></label></div><style id=yue_css>.yue{font:18px/1.62 -apple-system,BlinkMacSystemFont,segoe ui,droid sans,helvetica neue,pingfang sc,hiragino sans gb,droid sans fallback,microsoft yahei,sans-serif;color:#444443}.yue ::-moz-selection{background-color:#0003}.yue ::selection{background-color:#0003}.yue h1,.yue h2,.yue h3,.yue h4,.yue h5,.yue h6{font-family:-apple-system,BlinkMacSystemFont,segoe ui,droid sans,helvetica neue,pingfang sc,hiragino sans gb,droid sans fallback,microsoft yahei,sans-serif;color:#222223}.yue h1{font-size:1.8em;margin:.67em 0}.yue>h1{margin-top:0;font-size:2em}.yue h2{font-size:1.5em;margin:.83em 0}.yue h3{font-size:1.17em;margin:1em 0}.yue h4,.yue h5,.yue h6{font-size:1em;margin:1.6em 0 1em}.yue h6{font-weight:500}.yue p{margin-top:0;margin-bottom:1.24em}.yue a{color:#111;word-wrap:break-word;-webkit-text-decoration-color:#0006;text-decoration-color:#0006}.yue a:hover{color:#555;-webkit-text-decoration-color:#0009;text-decoration-color:#0009}.yue h1 a,.yue h2 a,.yue h3 a{text-decoration:none}.yue strong,.yue b{font-weight:700;color:#222223}.yue em,.yue i{font-style:italic;color:#222223}.yue img{max-width:100%;height:auto;margin:.2em 0}.yue a img{border:none}.yue figure{position:relative;clear:both;outline:0;margin:10px 0 30px;padding:0;min-height:100px}.yue figure img{display:block;max-width:100%;margin:auto auto 4px;box-sizing:border-box}.yue figure figcaption{position:relative;width:100%;text-align:center;left:0;margin-top:10px;font-weight:400;font-size:14px;color:#666665}.yue figure figcaption a{text-decoration:none;color:#666665}.yue hr{display:block;width:14%;margin:40px auto 34px;border:0;border-top:3px solid #dededc}.yue blockquote{margin:0 0 1.64em;border-left:3px solid #dadada;padding-left:12px;color:#666664}.yue blockquote a{color:#666664}.yue ul,.yue ol{margin:0 0 24px 6px;padding-left:16px}.yue ul{list-style-type:square}.yue ol{list-style-type:decimal}.yue li{margin-bottom:.2em}.yue li ul,.yue li ol{margin-top:0;margin-bottom:0;margin-left:14px}.yue li ul{list-style-type:disc}.yue li ul ul{list-style-type:circle}.yue li p{margin:.4em 0 .6em}.yue .unstyled{list-style-type:none;margin:0;padding:0}.yue code,.yue tt{color:gray;font-size:.96em;background-color:#f9f9f7;padding:1px 2px;border:1px solid #eee;border-radius:3px;font-family:Menlo,Monaco,Consolas,courier new,monospace;word-wrap:break-word}.yue pre{margin:1.64em 0;padding:7px;border:none;border-left:3px solid #dadada;padding-left:10px;overflow:auto;line-height:1.5;font-size:.96em;font-family:Menlo,Monaco,Consolas,courier new,monospace;color:#4c4c4c;background-color:#f9f9f7}.yue pre code,.yue pre tt{color:#4c4c4c;border:none;background:0 0;padding:0}.yue table{width:100%;max-width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:1.5em;font-size:.96em;box-sizing:border-box}.yue th,.yue td{text-align:left;padding:4px 8px 4px 10px;border:1px solid #dadada}.yue td{vertical-align:top}.yue tr:nth-child(even){background-color:#efefee}.yue iframe{display:block;max-width:100%;margin-bottom:30px}.yue figure iframe{margin:auto}.yue table pre{margin:0;padding:0;border:none;background:0 0}@media(min-width:1100px){.yue blockquote{margin-left:-24px;padding-left:20px;border-width:4px}.yue blockquote blockquote{margin-left:0}}</style><style id=ann_css>body{background-color:#464646!important}.mx-wc-main{margin:10px auto;width:auto;outline:none;border:1px solid #666;background-color:#fff;padding:10px}@media screen and (min-width:1600px){.mx-wc-main{width:900px!important}}.clipping-information{margin:10px auto;width:900px;background:#fff;padding:10px}.c1{background:#ecec00b2}.c2{background:#fc8d4cb2}.c3{background:#73e977b2}.c4{background:#5eeeecb2}.c5{background:#63b8ffb2}.c6{background:#a280aeb2}.underline{text-decoration:underline wavy green}.line-through{text-decoration:line-through double #f8e1e1}.tip{text-decoration:underline dotted #999}</style><style id=main_css></style><script id=load_js src=/static/load.js></script>